#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

/*
void handler(int signal)
{
    cout << "process get a signal: " << signal << endl;
}

int main()
{
    signal(SIGQUIT,handler);  //SIGQUIT:ctrl \   3号信号
    int cnt=5;
    while(1)
    {
        cout << "I am a crazy process" << endl;
        sleep(1);

        //1.int kill(pid_t pid, int sig); 向指定进程发送信号
        //2.int raise(int sig);  向调用该函数的进程发送信号
        //3.void abort(void);  向调用该函数的进行发送6号信号，并终止该进程（异常终止进程）
        //4.unsigned int alarm(unsigned int seconds);  闹钟
        cnt--;
        if(cnt==0)
        {
            int a=10;
            int b=0;
            int c=a/b;  //异常终止，发送8号信号   Floating point exception
          //  abort();
        }
    }
    return 0;
}
*/

/*

//信号集
void Printpending(sigset_t&pending)
{
    for(size_t i=31;i>0;i--)
    {
        if(sigismember(&pending,i))
        {
            cout<<"1";
        }
        else
        {
            cout<<"0";
        }
    }
    cout<<endl;
}

int main()
{
    sigset_t bset;  //信号集，1为有信号，0为无信号
    sigset_t oset;  //将修改前的信号集返回回来
    //对该信号集进行操作
    sigemptyset(&bset);
    sigaddset(&bset,2); //将2号信号位图置1
    sigaddset(&bset,4);
    sigaddset(&bset,5);
    sigaddset(&bset,6);
    //int  sigprocmask(int how,  const sigset_t *set, sigset_t*oldset);
    //how为处理方法
    //SIG_SETMASK:设置当前信号屏蔽字位set所指向的值
    sigprocmask(SIG_SETMASK,&bset,&oset); //  将信号屏蔽字设置进去了


    sigset_t pending; //pending表，打印出来
     sigemptyset(&pending);
    while(1)
    {
        sigpending(&pending); //获取pending表

        Printpending(pending);
        sleep(1);
    }
    return 0;
}


*/

// sigaction结构体
/*

void handler(int signal)
{
    while(1)
    {
        cout << "process get a signal: " << signal << "pid:"<<getpid()<<endl;
        sleep(1);
    }
}




int main()
{
    sigset_t bset;  //信号集，1为有信号，0为无信号
    sigset_t oset;  //将修改前的信号集返回回来
    //对该信号集进行操作
    sigemptyset(&bset);
    sigaddset(&bset,4);
    sigaddset(&bset,5);
    sigaddset(&bset,6);
    struct sigaction act,oact;
    memset(&act, 0, sizeof(act));
    memset(&oact, 0, sizeof(oact));
    //给sa_handler赋值为函数指针，表示自定义捕捉信号
    //给sa_handler复制SIG_INT，表示忽略动作：
    //给sa_handler赋值为SIG_DFL，表示采取默认动作：
    act.sa_handler = handler;  //类似中断服务函数

    act.sa_mask=bset;  //调用信号处理函数时，除了当前信号被自动屏蔽之外，还希望自动屏蔽另外一些信号
    sigaction(2,&act,&oact);
    while(1)
    {
        cout << "I am a crazy process" << endl;
        sleep(1);
    }
    return 0;
}

*/

// 在执行中断服务函数时，捕捉到的该信号会被屏蔽掉，如果有多个子进程在执行中断服务函数时退出的话
// 那么这个信号会被屏蔽 ，导致内存泄露

void handler(int signal)
{
    while (1)
    {
        // 使用非阻塞等待来回收
        pid_t rid;
        while ((rid = waitpid(-1, nullptr, WNOHANG)) > 0)
        {
            cout << "I am process: " << getpid() << ", catch a signo: " << signal << "child process quit: " << rid << endl;
        }
    }
}

int main()
{
    //signal(SIGCHLD, handler);
    signal(SIGCHLD,SIG_IGN);  //不通知父进程，自动回收僵尸进程（LINUX）
    for (int i = 0; i < 10; i++)
    {
        pid_t id = fork();
        if (id == 0)
        {
            // 子进程
            int cnt = 10;
            while (cnt)
            {
                cout << "我是子进程, pid: " << getpid() << " 当前的cnt: " << cnt-- << endl;
                sleep(1);
            }
            cout << "子进程退出， 进入僵尸状态" << endl;
            exit(0);
        }
        // sleep(1);
    }
    while (true)
    {
        cout << "我是父进程，我正在运行：" << getpid() << endl;
        sleep(1);
    }

    return 0;
}
